﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Office.Interop.PowerPoint;
using log4net;
using System.Reflection;

namespace ThreeByte.ActiveDeck.Content
{
    public static class ModelInspector
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(ModelInspector));

        public static string Dump(Sequence seq) {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("[Sequence]: {0} Effects", seq.Count);
            sb.AppendLine();
            foreach(Effect e in seq){
                sb.AppendFormat("{0}", Dump(e));
            }
            return sb.ToString();
        }

        public static string Dump(Effect e) {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("[Effect]: DisplayName: {0} EffectType: {1} AfterEffect: {2}", e.DisplayName, e.EffectType, e.EffectInformation.AfterEffect);
            sb.AppendLine();
            foreach(AnimationBehavior b in e.Behaviors) {
                sb.AppendFormat("\t{0}", Dump(b));
            }
            return sb.ToString();
        }

        private static string Dump(AnimationBehavior b) {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("[Behaviors]: Type: {0} Duration: {1}", b.Type, b.Timing.Duration);
            sb.AppendLine();
            sb.AppendFormat("\t\t{0}", Dump(b.Timing));
            if(b.Type == MsoAnimType.msoAnimTypeProperty) {
                sb.AppendFormat("\t\t{0}", Dump(b.PropertyEffect));
            } else if(b.Type == MsoAnimType.msoAnimTypeSet) {
                sb.AppendFormat("\t\t{0}", Dump(b.SetEffect));
            } else if(b.Type == MsoAnimType.msoAnimTypeMotion) {
                sb.AppendFormat("\t\t{0}", Dump(b.MotionEffect));
            } else if(b.Type == MsoAnimType.msoAnimTypeFilter) {
                sb.AppendFormat("\t\t{0}", Dump(b.FilterEffect));
            } else if(b.Type == MsoAnimType.msoAnimTypeRotation) {
                sb.AppendFormat("\t\t{0}", Dump(b.RotationEffect));
            }
            return sb.ToString();
        }

        private static string Dump(RotationEffect rotationEffect) {
            //throw new NotImplementedException();
            return "\n";
        }

        private static string Dump(FilterEffect filterEffect) {
            StringBuilder sb = new StringBuilder();
            sb.Append("[FilterEffect]:");
            foreach (string s in new string[] { "Type", "Subtype", "Reveal" }) {

                try {
                    PropertyInfo pis = typeof(FilterEffect).GetProperty(s);
                    sb.AppendFormat(" {0}: {1}", s, pis.GetValue(filterEffect, null));
                } catch {
                    //Ignore
                }
            }
            return sb.AppendLine().ToString();
        }

        private static string Dump(MotionEffect motionEffect) {
            //throw new NotImplementedException();
            return "\n";
        }

        private static string Dump(Timing timing) {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("[Timing] Duration: {0} Accelerate: {1} Decelerate: {2} AutoReverse: {3} BounceEnd: {4} RepeatCount: {5} Restart: {6} Speed: {10}",
                                    timing.Duration,
                                    timing.Accelerate,
                                    timing.Decelerate,
                                    timing.AutoReverse,
                                    timing.BounceEnd,
                                    timing.RepeatCount,
                                    timing.Restart,
                                    timing.RewindAtEnd,
                                    timing.SmoothEnd,
                                    timing.SmoothStart,
                                    timing.Speed,
                                    //timing.TriggerBookmark,
                                    timing.TriggerDelayTime,
                                    timing.TriggerShape
                                    //timing.TriggerType
                                    );
            sb.AppendLine();
            return sb.ToString();
        }

        private static string Dump(SetEffect setEffect) {

            StringBuilder sb = new StringBuilder();
            sb.Append("[SetEffects]:");
            foreach(string s in new string[]{"Property", "To"}) {

                try {
                    PropertyInfo pis = typeof(SetEffect).GetProperty(s);
                    sb.AppendFormat(" {0}: {1}", s, pis.GetValue(setEffect, null));
                } catch {
                    //Ignore
                }
            }
            return sb.AppendLine().ToString();
        }

        private static string Dump(PropertyEffect propertyEffect) {
            StringBuilder sb = new StringBuilder();
            try {
                sb.AppendFormat("[PropertyEffect] Property: {0} From: {1} To: {2}",
                                    propertyEffect.Property,
                                    propertyEffect.From,
                                    propertyEffect.To);
            } catch (Exception ex) {
                log.Warn("Cannot dump PropertyEffect", ex);
            }
            sb.AppendLine();
            foreach(AnimationPoint p in propertyEffect.Points){
                sb.AppendFormat("{0}", Dump(p));
            }
            return sb.ToString();
        }

        private static string Dump(AnimationPoint p) {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("\t\t\t[AnimationPoint] Formula: {0} Time: {1} Value: {2}", p.Formula, p.Time,p.Value);
            return sb.AppendLine().ToString();
        }

    }
}
